package net.keebook.webapp.ws;

import java.util.TimeZone;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

import net.keebook.webapp.dao.GroupDao;
import net.keebook.webapp.dao.PasswordDao;
import net.keebook.webapp.dao.SettingDao;
import net.keebook.webapp.entity.ItemGroup;
import net.keebook.webapp.entity.KeeBook;
import net.keebook.webapp.entity.PasswordItem;
import net.keebook.webapp.entity.User;
import net.keebook.webapp.model.SessionModel;
import net.keebook.webapp.util.AccessRight;
import net.keebook.webapp.util.DateUtil;
import net.keebook.webapp.util.SettingId;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


@Path("/{username}/setitem")
@Stateless
public class SetItemService extends WebService {
	@Inject
	private PasswordDao passwordDao;
	@Inject
	private SettingDao settingDao;
	@Inject
	private GroupDao groupDao;
	
	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	public String saveSettings(@Context HttpServletRequest request, @PathParam("username") String username, String jsonString) {
		Logger.getLogger(this.getClass()).info("Incoming request");
		Logger.getLogger(this.getClass()).trace("Request string: " + jsonString);
		
		JSONObject input = getInput(jsonString);
		JSONObject result = new JSONObject();
		try {
			String auth = input.has("auth") ? input.getString("auth") : AUTH_PASSWORD;
			String password = input.getString("password");
			String keeBookId = input.getString("keeBook");
			String keeBookChecksum = input.getString("keeBookChecksum");
			JSONArray items = input.getJSONArray("items");
			
			HttpSession httpSession = request.getSession(true);
			SessionModel sessionModel = SessionModel.getInstance(httpSession);
			
			// Authentication
			User user = authenticate(username, password, auth, sessionModel);
			if (user == null) {
				Logger.getLogger(this.getClass()).warn("Authentication failed for user " + username);
				result.put("authSuccess", false);
				result.put("success", false);
				return getResponse(result);
			}
			username = user.getUsername();
			
			// Open Key Box
			KeeBook keeBook = getKeeBook(keeBookId, keeBookChecksum);
			if (keeBook == null || !getKeeBookDao().canAccess(user.getId(), keeBook.getId(), AccessRight.READ_WRITE)) {
				Logger.getLogger(this.getClass()).warn("Kee Book authentication failed for user " + username + " and kee book " + keeBookId);
				result.put("authSuccess", false);
				result.put("success", false);
				return getResponse(result);
			}
			
			Logger.getLogger(this.getClass()).info("User " + username + " authenticated successfully (user id: "+user.getExposableId()+" / kee book id: "+keeBook.getExposableId()+")");
			result.put("authSuccess", true);
			
			TimeZone systemTimeZone = TimeZone.getTimeZone(getSettingDao().get(SettingId.SYSTEM_TIMEZONE).getValue());
			int numSuccessful = 0;
			JSONArray resultItemsIds = new JSONArray();
			
			for (int i=0; i<items.length(); i++) {
				JSONObject item = items.getJSONObject(i);
				PasswordItem passwordItem;
				if (item.has("id")) {
					passwordItem = getPasswordDao().get(item.getString("id"));
				} else {
					passwordItem = new PasswordItem();
					passwordItem.setCreationTime(DateUtil.getUtcTimestamp(systemTimeZone));
					passwordItem.setKeeBook(keeBook);
				}
				if (item.has("title")) passwordItem.setTitle(item.getString("title"));
				if (item.has("username")) passwordItem.setUsername(item.getString("username"));
				if (item.has("password")) passwordItem.setPassword(item.getString("password"));
				if (item.has("url")) passwordItem.setUrl(item.getString("url"));
				if (item.has("notes")) passwordItem.setNotes(item.getString("notes"));
				if (item.has("group")) {
					ItemGroup group = getGroupDao().get(item.getString("group"));
					passwordItem.setGroup(group);
				}
				passwordItem.setLastModification(DateUtil.getUtcTimestamp(systemTimeZone));
				if (item.has("id")) {
					getPasswordDao().update(passwordItem);
				} else {
					getPasswordDao().store(passwordItem);
				}
				resultItemsIds.put(passwordItem.getExposableId());
				numSuccessful++;
			}
			
			result.put("success", true);
			result.put("count", numSuccessful);
			result.put("itemIds", resultItemsIds);
		} catch (JSONException e) {
			return getResponse("{'success': false, 'authSuccess': false}");
		}
		
		return getResponse(result);
	}

	public PasswordDao getPasswordDao() {
		return passwordDao;
	}

	public void setPasswordDao(PasswordDao passwordDao) {
		this.passwordDao = passwordDao;
	}

	public SettingDao getSettingDao() {
		return settingDao;
	}

	public void setSettingDao(SettingDao settingDao) {
		this.settingDao = settingDao;
	}

	public GroupDao getGroupDao() {
		return groupDao;
	}

	public void setGroupDao(GroupDao groupDao) {
		this.groupDao = groupDao;
	}
}
